import React, { ReactNode, useContext } from "react";
import { useQueryClient } from "react-query";
import * as auth from '../auth-provider';
import { FullPageErrorFallback, FullPageLoading } from "../components/lib";
import { User } from "../types";
import { useMount } from "../utils";
import { http } from "../utils/http";
import { useAsync } from "../utils/use-async";
interface AuthForm{
    username:string,
    password:string
}

//初始化时调用，
const bootstrapUser = async ()=>{
    let user = null;
    const token = auth.getToken();
    if(token){
        const data = await http('me',{token});
        user = data.user;
    }
    return user;
}

const AuthContext = React.createContext<{
    user:User|null,
    login:(form:AuthForm)=>Promise<void>,
    register:(form:AuthForm)=>Promise<void>,
    logout:()=> Promise<void>
}|undefined>(undefined);
//主要是用在dev-tool里
AuthContext.displayName = 'AuthContext';

export const AuthProvider = ({children}:{children:ReactNode})=>{
    //这里初始化为null会有一个问题，登录后页面刷新会重新设置为null导致返回登录页面
    // const [user,setUser] = useState<User|null>(null);
    //通过usAsync改造
    const {data:user,error,isLoading,isError,isIdle,run,setData:setUser} = useAsync<User | null>();
    const queryClient = useQueryClient();
    const login = (form:AuthForm)=>auth.login(form).then(setUser);
    const register = (form:AuthForm)=>auth.register(form).then(setUser);
    const logout = ()=>auth.logout().then(()=>{
        setUser(null);
        queryClient.clear();
    });

    useMount(()=>{
        run(bootstrapUser());
    });

    if(isIdle || isLoading){
        return <FullPageLoading />
    }

    if(isError){
        return <FullPageErrorFallback error={error}/>
    }

    return <AuthContext.Provider children={children} value={{user,login,register,logout}} />
}

export const useAuth = ()=>{
    const context = useContext(AuthContext);
    if(!context){
        throw new Error('useAuth必须在AuthProvider中使用');
    }
    return context;
}